package com.paic.mhis.hcpms.quota.exportword.utils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;

import com.paic.mhis.hcpms.common.document.util.Constant;
import com.paic.mhis.hcpms.quota.calculationreport.kpiinterface.dto.KpiConditionDTO;
import com.paic.mhis.hcpms.quota.settlement.common.Constants;

/**
 * Description: word数据计算的相关方法
 * 
 * @author: EX-YANGLIGANG001
 * @version:
 */

public class WordReportCalculateHelper {

	private static final Logger logger = Logger.getLogger(WordReportCalculateHelper.class);

	private static WordReportCalculateHelper calculateHelper = new WordReportCalculateHelper();

	public static WordReportCalculateHelper getInstance() {
		return calculateHelper;
	}

	public String getStartDate(String endDate, int number) {
		Calendar date = Calendar.getInstance();
		String startDate = "";
		SimpleDateFormat sft = new SimpleDateFormat("yyyy-MM");
		try {
			if (StringUtils.hasText(endDate)) {
				date.setTime(sft.parse(endDate));
				date.add(Calendar.MONTH, number);
				startDate = sft.format(date.getTime());
			}
		} catch (ParseException e) {
			logger.error("-------------------计算开始日期异常-----------------------", e);
		}
		return startDate;
	}

	public Map<String, Integer> createOrderList(String startDate, String endDate) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		Calendar date = Calendar.getInstance();
		SimpleDateFormat sft = new SimpleDateFormat("yyyy-MM");
		int length = 0;
		try {
			if (StringUtils.hasText(startDate) && StringUtils.hasText(endDate)) {
				date.setTime(sft.parse(startDate));
				String data = "";
				if (sft.parse(startDate).getTime() <= sft.parse(endDate).getTime()) {
					do {
						data = sft.format(date.getTime());
						map.put(data, length);
						length++;
						date.add(Calendar.MONTH, Constant.MONTH_FIRST);
					} while (!data.equals(endDate));
				}
			}
		} catch (ParseException e) {
			logger.error("解析日期异常：", e);
		}
		return map;
	}

	public List<BigDecimal> createSetListValue(int listSize, BigDecimal value) {
		List<BigDecimal> list = new ArrayList<BigDecimal>();
		for (int i = 0; i < listSize; i++) {
			list.add(i, value);
		}
		return list;
	}

	public BigDecimal filterNullValue(BigDecimal value) {
		if (null == value)
			return new BigDecimal(0);
		else
			return value;
	}

	// --------ex-yangligang001
	/**
	 * Description: 判断比率是否小于0
	 * 
	 * @param ratio
	 * @return boolean
	 */
	public boolean compareToZero(BigDecimal ratio) {
		boolean lessThan = false;
		if (ratio.compareTo(new BigDecimal(0)) < 0) {
			lessThan = true;
		}
		return lessThan;
	}

	/**
	 * Description: 判断比率是否异常
	 * 
	 * @param ratio
	 * @return boolean
	 */
	public boolean judgeIndUnusual(BigDecimal ratio, BigDecimal upperLimit, BigDecimal lowerLimit) {
		boolean isIndUnusal = false;
		if (ratio.compareTo(lowerLimit) < 0) {
			isIndUnusal = true;
		}
		if (ratio.compareTo(upperLimit) > 0) {
			isIndUnusal = true;
		}
		return isIndUnusal;
	}

	/**
	 * Description: 单个数据的保留2为小数
	 * 
	 * @param bigDecimal
	 * @return String
	 */
	public String toFixedPercent(BigDecimal bigDecimal) {
		DecimalFormat df = new DecimalFormat("0.00");
		String fixedDate = "0.00";
		if (bigDecimal != null && new BigDecimal(0).compareTo(bigDecimal) != 0) {
			fixedDate = df.format(bigDecimal);
		}
		return fixedDate;
	}

	/**
	 * Description: 单个数据的保留2为小数
	 * 
	 * @param bigDecimal
	 * @return String
	 */
	public String toFixedTwoPercent(BigDecimal bigDecimal) {

		DecimalFormat df = new DecimalFormat("0.00");
		String fixedDate = "0.00";
		if (bigDecimal != null && new BigDecimal(0).compareTo(bigDecimal) != 0) {
			BigDecimal correctNum = bigDecimal.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			fixedDate = df.format(correctNum);
		}
		return fixedDate;
	}

	/**
	 * Description: 单个数据的保留1位小数
	 * 
	 * @param bigDecimal
	 * @return String
	 */
	public String toFixedOnePercent(BigDecimal bigDecimal) {

		DecimalFormat df = new DecimalFormat("0.0");
		String fixedDate = "0.0";
		if (bigDecimal != null && new BigDecimal(0).compareTo(bigDecimal) != 0) {
			BigDecimal correctNum = bigDecimal.divide(new BigDecimal(1), 1, BigDecimal.ROUND_HALF_UP);
			fixedDate = df.format(correctNum);
		}
		return fixedDate;
	}

	/**
	 * Description: 单个数据的取整
	 * 
	 * @param bigDecimal
	 * @return String
	 */

	public String toFixedOne(BigDecimal bigDecimal) {

		String correctNum = " ";
		if (bigDecimal != null && new BigDecimal(0).compareTo(bigDecimal) != 0) {
			correctNum = bigDecimal.divide(new BigDecimal(1), 0, BigDecimal.ROUND_HALF_UP).toString();
		}
		return correctNum;
	}

	/**
	 * Description: 取数据的绝对值， 若没有就将数据置0
	 * 
	 * @param value
	 * @return BigDecimal
	 */
	public BigDecimal getAbsVaule(BigDecimal value) {
		if (null != value) {
			return value.abs();
		}
		return new BigDecimal(0);
	}

	/**
	 * 转换成亿为单位并且保留两位小数
	 * 
	 * @param list
	 */
	public List<BigDecimal> toFixedList(List<BigDecimal> list) {
		List<BigDecimal> returnList = new ArrayList<BigDecimal>();
		for (BigDecimal bigDecimal : list) {
			returnList.add(yuan2Yi(bigDecimal));
		}
		return returnList;
	}

	/**
	 * 元转为亿
	 * 
	 * @param yuan
	 * @return Bigdecimal
	 */
	public BigDecimal yuan2Yi(BigDecimal yuan) {
		if (new BigDecimal(0).compareTo(yuan) == 0) {
			return new BigDecimal(0);
		} else
			return yuan.divide(new BigDecimal(100000000), 2, BigDecimal.ROUND_HALF_UP);
	}

	public String getTotalFeeTendencyMessage(List<BigDecimal> toCompareChaList, List<BigDecimal> toComparePerList,
			Map<String, String> kpiLimitMap) {
		String message = " ";
		if (GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("chainDown"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("chainUpper"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("periodDown"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("periodUpper"))) {
			return message;
		}

		if (new BigDecimal(kpiLimitMap.get("chainDown")).compareTo(toCompareChaList.get(Constant.MONTH_ELEVEN)) <= 0
				&& new BigDecimal(kpiLimitMap.get("chainUpper")).compareTo(toCompareChaList.get(Constant.MONTH_ELEVEN)) >= 0
				&& new BigDecimal(kpiLimitMap.get("periodDown")).compareTo(toComparePerList.get(Constant.MONTH_ELEVEN)) <= 0
				&& new BigDecimal(kpiLimitMap.get("periodUpper"))
						.compareTo(toComparePerList.get(Constant.MONTH_ELEVEN)) >= 0) {
			message = "无明显异常";
		} else {
			message = "可能存在异常";
		}
		return message;
	}

	public String getTendencyMessage(BigDecimal toCompareNum1, BigDecimal toCompareNum2, Map<String, Object> kpiLimitMap) {
		String message = " ";
		if (GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("chainDown"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("chainUpper"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("periodDown"))
				|| GeneralMethods.getInstance().isEmptyString((String) kpiLimitMap.get("periodUpper"))) {
			return message;
		}

		if (new BigDecimal((String) kpiLimitMap.get("chainDown")).compareTo(toCompareNum1) <= 0
				&& new BigDecimal((String) kpiLimitMap.get("chainUpper")).compareTo(toCompareNum1) >= 0
				&& new BigDecimal((String) kpiLimitMap.get("periodDown")).compareTo(toCompareNum2) <= 0
				&& new BigDecimal((String) kpiLimitMap.get("periodUpper")).compareTo(toCompareNum2) >= 0) {
			message = "无明显异常";
		} else {
			message = "可能存在异常";
		}
		return message;
	}

	public String getRatioCompareResult(BigDecimal toCompareNum) {
		String message = "";
		if (toCompareNum.compareTo(new BigDecimal(0)) >= 0) {
			message = "增加";
		}
		if (toCompareNum.compareTo(new BigDecimal(0)) < 0) {
			message = "降低";
		}
		return message;
	}

	public String getRatioCompareResult(List<BigDecimal> toCompareList) {
		String message = "";
		if (toCompareList.get(11).compareTo(new BigDecimal(0)) >= 0) {
			message = "增加";
		}
		if (toCompareList.get(11).compareTo(new BigDecimal(0)) < 0) {
			message = "降低";
		}
		return message;
	}

	public String getRatioCompareScope(BigDecimal toCompareLiNum1, String upperLimit, String downLimit) {
		String message = " ";
		if (GeneralMethods.getInstance().isEmptyString(upperLimit)
				|| GeneralMethods.getInstance().isEmptyString(downLimit)) {
			return message;
		}
		if (new BigDecimal(downLimit).compareTo(toCompareLiNum1) <= 0
				&& new BigDecimal(upperLimit).compareTo(toCompareLiNum1) >= 0) {
			message = "未超出";
		} else {
			message = "已超出";
		}
		return message;
	}

	public String getRatioCompareScope(List<BigDecimal> toCompareList, String upperLimit, String downLimit) {
		String message = " ";
		if (GeneralMethods.getInstance().isEmptyString(upperLimit)
				|| GeneralMethods.getInstance().isEmptyString(downLimit)) {
			return message;
		}
		if (new BigDecimal(downLimit).compareTo(toCompareList.get(Constant.INDEX_ELEVEN)) <= 0
				&& new BigDecimal(upperLimit).compareTo(toCompareList.get(Constant.INDEX_ELEVEN)) >= 0) {
			message = "未超出";
		} else {
			message = "已超出";
		}
		return message;
	}

	public String getRiskMessage(List<BigDecimal> toCompareList1, List<BigDecimal> toCompareList2,
			Map<String, String> kpiLimit) {

		String message = " ";
		if (GeneralMethods.getInstance().isEmptyString(kpiLimit.get("periodUpper"))
				|| GeneralMethods.getInstance().isEmptyString(kpiLimit.get("chainUpper"))
				|| GeneralMethods.getInstance().isEmptyString(kpiLimit.get("periodDown"))
				|| GeneralMethods.getInstance().isEmptyString(kpiLimit.get("chainDown"))) {
			return message;
		}

		boolean flagPeriod = true;
		boolean flagChain = true;
		for (int i = 0; i < toCompareList1.size(); i++) {
			if (toCompareList1.get(i).compareTo(new BigDecimal(kpiLimit.get("periodDown"))) < 0
					|| toCompareList1.get(i).compareTo(new BigDecimal(kpiLimit.get("periodUpper"))) > 0) {
				flagPeriod = false;
				break;
			}
		}
		for (int i = 0; i < toCompareList2.size(); i++) {
			if (toCompareList2.get(i).compareTo(new BigDecimal(kpiLimit.get("chainDown"))) < 0
					|| toCompareList2.get(i).compareTo(new BigDecimal(kpiLimit.get("chainUpper"))) > 0) {
				flagChain = false;
				break;
			}
		}
		if (flagPeriod && flagChain) {
			message = "较小";
		} else {
			message = "较大,需要加强监控";
		}

		return message;
	}

	public String getRisk(List<BigDecimal> toCompareList1, List<BigDecimal> toCompareList2, BigDecimal[] yoyLimits,
			BigDecimal[] momLimits, boolean healthFlag) {
		if (healthFlag) {
			return " ";
		}
		String message = "";
		boolean flagPeriod = true;
		boolean flagChain = true;
		for (int i = 0; i < toCompareList1.size(); i++) {
			if (toCompareList1.get(i).compareTo(yoyLimits[1]) < 0 || toCompareList1.get(i).compareTo(yoyLimits[0]) > 0) {
				flagPeriod = false;
				break;
			}
		}
		for (int i = 0; i < toCompareList2.size(); i++) {
			if (toCompareList2.get(i).compareTo(momLimits[1]) < 0 || toCompareList2.get(i).compareTo(momLimits[0]) > 0) {
				flagChain = false;
				break;
			}
		}
		if (flagPeriod && flagChain) {
			message = "较小";
		} else {
			message = "较大,需要加强监控";
		}

		return message;
	}

	/**
	 * 转换成万为单位并且保留两位小数
	 * 
	 * @param list
	 */
	public List<BigDecimal> toFixedUniqueOrgList(List<BigDecimal> list) {
		List<BigDecimal> returnList = new ArrayList<BigDecimal>();
		for (BigDecimal bigDecimal : list) {
			returnList.add(yuanToTenThousands(bigDecimal));
		}
		return returnList;
	}

	/**
	 * 元转化为百万
	 */
	public BigDecimal yuanToMillion(BigDecimal yuan) {
		if (new BigDecimal(0).compareTo(yuan) == 0) {
			return new BigDecimal(0);
		} else
			return yuan.divide(new BigDecimal(1000000), 2, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 元转化为万
	 */
	public BigDecimal yuanToTenThousands(BigDecimal yuan) {
		if (new BigDecimal(0).compareTo(yuan) == 0) {
			return new BigDecimal(0);
		} else
			return yuan.divide(new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP);
	}

	/**
	 * 
	 * 费用占比值取两位有效小数
	 */
	public List<BigDecimal> toFixedPercentList(List<BigDecimal> list) {
		List<BigDecimal> returnList = new ArrayList<BigDecimal>();
		for (BigDecimal bigDecimal : list) {
			if (new BigDecimal(0).compareTo(bigDecimal) == 0) {
				returnList.add(new BigDecimal(0));
			} else {
				returnList.add(bigDecimal.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP));
			}
		}
		return returnList;
	}

	/**
	 * Description: 同比环比检验   
	 * @param flag
	 * @return
	 */
	public String checkFlag(String flag) {
		if ("  ".equals(flag)) {
			return "  ";
		}
		if ("无明显异常".equals(flag)) {
			return "未超出";
		}
		return "已超出";
	}

	/**
	 * Description:  费用是否存在异常  
	 * @param ratio
	 * @param map
	 * @param type
	 * @return
	 */
	public String checkOneRation(BigDecimal ratio, Map<String, Object> map, int type) {

		if (null == map.get("mom_upper") || null == map.get("yoy_upper")) {
			return "  ";
		}

		BigDecimal upRatio = null;
		BigDecimal downRatio = null;
		switch (type) {
		case 1:
			upRatio = new BigDecimal(map.get("yoy_upper").toString());
			downRatio = new BigDecimal(map.get("yoy_lower").toString());
			break;
		case 2:
			upRatio = new BigDecimal(map.get("mom_upper").toString());
			downRatio = new BigDecimal(map.get("mom_lower").toString());
			break;
		}
		if (ratio.compareTo(downRatio) >= 0 && ratio.compareTo(upRatio) <= 0) {
			return "无明显异常";
		}
		return "可能存在异常";
	}

	/**
	 * Description:  同比环比  有无异常
	 * @param periodRatio
	 * @param chainRatio
	 */
	public String checkRation(BigDecimal periodRatio, BigDecimal chainRatio, Map<String, Object> map) {
		if (null == map.get("mom_lower")) {
			return "  ";
		}
		if (chainRatio.compareTo(new BigDecimal(map.get("mom_lower").toString())) >= 0
				&& chainRatio.compareTo(new BigDecimal(map.get("mom_upper").toString())) <= 0
				&& periodRatio.compareTo(new BigDecimal(map.get("yoy_lower").toString())) >= 0
				&& periodRatio.compareTo(new BigDecimal(map.get("yoy_upper").toString())) <= 0) {
			return "无明显异常";
		}

		return "可能存在异常";
	}

	/**
	 * Description:  查询KPI阈值上下限  
	 * @param map
	 * @param kpiLimitValue
	 * @param kpiCode
	 * @return
	 */
	public Map<String, Object> setRatioYoyAndMom(Map<String, Object> map, Map<String, Object> kpiLimitValue,
			String kpiCode, String realKpiCode) {
		map.put(kpiCode + "_yoy_upper_end", checkKpiLimitValue(kpiLimitValue.get(realKpiCode + "_yoy_upper_end")));
		map.put(kpiCode + "_yoy_lower_end", checkKpiLimitValue(kpiLimitValue.get(realKpiCode + "_yoy_lower_end")));
		map.put(kpiCode + "_mom_upper_end", checkKpiLimitValue(kpiLimitValue.get(realKpiCode + "_mom_upper_end")));
		map.put(kpiCode + "_mom_lower_end", checkKpiLimitValue(kpiLimitValue.get(realKpiCode + "_mom_lower_end")));
		return map;
	}

	public Object checkKpiLimitValue(Object obj) {
		if (null != obj) {
			return obj;
		}

		return "   ";
	}

	/**
	 * 设置查询条件
	 */
	public KpiConditionDTO getKpiConditionByKpiCode(Map<String, Object> paramsMap, String kpiCode) {
		String visitType = (String) paramsMap.get("visitType");
		String month = (String) paramsMap.get("currentDate");
		String regionCode = (String) paramsMap.get("regionCode");
		KpiConditionDTO con = new KpiConditionDTO();
		con.setVisitType(visitType);
		con.setKpiCode(kpiCode);
		con.setKpiTime(month);
		con.setPeriod(Constants.perion_13);
		con.setSociationCode(regionCode);
		return con;
	}

	// 新预测公式下，同比计算公式
	public List<BigDecimal> getPeriodRatioPredict(List<BigDecimal> threeAvePreTotValList,
			List<BigDecimal> totalPayList, List<BigDecimal> monthPeriodList) {
		List<BigDecimal> periodList = new ArrayList<BigDecimal>();
		BigDecimal firstMonPeriod = new BigDecimal(0);
		BigDecimal secondMonPeriod = new BigDecimal(0);
		BigDecimal thirdMonPeriod = new BigDecimal(0);
		if (totalPayList.get(Constant.MONTH_TWENTYFOUR).compareTo(new BigDecimal(0)) != 0) {
			firstMonPeriod = threeAvePreTotValList.get(Constant.INDEX_ONE)
					.subtract(totalPayList.get(Constant.MONTH_TWENTYFOUR))
					.divide(totalPayList.get(Constant.MONTH_TWENTYFOUR), Constant.NUMBER_TWO, BigDecimal.ROUND_HALF_UP);
		}
		if (totalPayList.get(Constant.MONTH_TWENTYFIVE).compareTo(new BigDecimal(0)) != 0) {
			secondMonPeriod = threeAvePreTotValList.get(Constant.INDEX_TWO)
					.subtract(totalPayList.get(Constant.MONTH_TWENTYFIVE))
					.divide(totalPayList.get(Constant.MONTH_TWENTYFIVE), Constant.NUMBER_TWO, BigDecimal.ROUND_HALF_UP);
		}

		if (totalPayList.get(Constant.MONTH_TWENTYSIX).compareTo(new BigDecimal(0)) != 0) {
			thirdMonPeriod = threeAvePreTotValList.get(Constant.INDEX_THREE)
					.subtract(totalPayList.get(Constant.MONTH_TWENTYSIX))
					.divide(totalPayList.get(Constant.MONTH_TWENTYSIX), Constant.NUMBER_TWO, BigDecimal.ROUND_HALF_UP);
		}
		periodList.add(monthPeriodList.get(Constant.INDEX_ELEVEN));
		periodList.add(firstMonPeriod);
		periodList.add(secondMonPeriod);
		periodList.add(thirdMonPeriod);

		return periodList;
	}

	// 新预测公式下，环比计算公式
	public List<BigDecimal> getChainRatioPredict(List<BigDecimal> threeAvePreTotValList, List<BigDecimal> monthChainList) {
		List<BigDecimal> chainList = new ArrayList<BigDecimal>();
		BigDecimal chain = new BigDecimal(0);
		for (int i = 0; i < threeAvePreTotValList.size() - Constant.NUMBER_ONE; i++) {
			if (threeAvePreTotValList.get(i).compareTo(new BigDecimal(0)) != 0) {
				chain = (threeAvePreTotValList.get(i + Constant.NUMBER_ONE).subtract(threeAvePreTotValList.get(i)))
						.divide(threeAvePreTotValList.get(i), Constant.NUMBER_TWO, BigDecimal.ROUND_HALF_UP);
			}
			chainList.add(chain);
		}
		chainList.add(0, monthChainList.get(Constant.INDEX_ELEVEN));
		return chainList;
	}

}
